package models

import (
	"errors"
	"fmt"
	"github.com/sirupsen/logrus"
	"hc_server/pkg/setting"
	time2 "hc_server/pkg/time"
	"hc_server/routers/response/deviceResponse"
	"time"
)

type Device struct {
	Model
	DeviceSn       string     `json:"device_sn" form:"device_sn" mapstructure:"device_sn" gorm:"comment:'设备sn'"`
	DeviceModelId  int        `json:"device_model_id" form:"device_model_id" mapstructure:"device_model_id" gorm:"comment:'设备型号 device_models主键id'"`
	DeviceTUSN     string     `json:"device_tusn" form:"device_tusn" mapstructure:"device_tusn" gorm:"comment:'设备TUSN'"`
	Iccid          string     `json:"iccid" form:"iccid" mapstructure:"iccid" gorm:"comment:'iccid'"`
	PaymentCode    string     `json:"payment_code" form:"payment_code" mapstructure:"payment_code" gorm:"comment:'收款码编号，只有码牌有值'"`
	DeliveryTime   *time.Time `json:"delivery_time" form:"delivery_time" mapstructure:"delivery_time" gorm:"comment:'出库时间'"`
	BindingTime    *time.Time `json:"binding_time" form:"binding_time" mapstructure:"binding_time" gorm:"comment:'绑定时间'"`
	BaseAgentId    int        `json:"base_agent_id" form:"base_agent_id" mapstructure:"base_agent_id" gorm:"comment:'直属上级id'"`
	AgentId        int        `json:"agent_id" form:"agent_id" mapstructure:"agent_id" gorm:"comment:'代理商id';not null"`
	MerchantId     int        `json:"merchant_id" form:"merchant_id" mapstructure:"merchant_id" gorm:"comment:'所属商户id'"`
	StockStatus    int        `json:"stock_status" form:"stock_status" mapstructure:"stock_status" gorm:"comment:'库存状态：0=待出库 1=已出库'"`
	BindingStatus  int        `json:"binding_status" form:"binding_status" mapstructure:"binding_status" gorm:"comment:'绑定状态：0=未绑定 1=已绑定'"`
	ActivateStatus int        `json:"activate_status" form:"activate_status" mapstructure:"activate_status" gorm:"default:0;comment:'激活状态：0=未激活 1=伪激活 2=已激活'"`
}

// DeviceInfoAdd 添加设备
func DeviceInfoAdd(dev Device) error {
	err := db.Create(&dev).Error
	if err != nil {
		logrus.WithError(err).Errorf("添加设备失败 err:%v,dev:%v", err, dev)
		return errors.New("添加设备失败")
	}
	return nil
}

// GetDeviceById 通过id获取设备信息
func GetDeviceById(id any) (*Device, error) {
	var dev *Device
	db.Where("id = ?", id).First(&dev)
	if dev.ID == 0 {
		return nil, errors.New("设备不存在")
	}
	return dev, nil
}

// DeviceList 获取device设备列表
func DeviceList(merchantId int) ([]*deviceResponse.GetDeviceListResponse, error) {
	var result = make([]*deviceResponse.GetDeviceListResponse, 0)
	err := db.Model(&Device{}).Select("id,name,status,device_no AS no,created_at AS time").Where("merchant_id = ?", merchantId).Scan(&result).Error
	if err != nil {
		logrus.WithError(err).Errorf("获取device设备列表失败 err:%v,merchantId:%v", err, merchantId)
		return nil, errors.New("获取device设备列表失败")
	}
	return result, nil
}

// DeviceInfoSearch 设备信息查询
func DeviceInfoSearch(agentId, pageNum, pageSize int, keyword string) (map[string]interface{}, error) {
	return nil, nil
}

// DeviceInfoList 设备信息列表
func DeviceInfoList(agentId, pageNum, pageSize int) (map[string]interface{}, error) {
	var (
		result          = make([]*deviceResponse.GetDeviceInfoListResponse, 0)
		count           int64 //总数
		dispatchCount   int64 //待出库
		dispatchedCount int64 //已出库
		bindingCount    int64 //已绑定
		unBindingCount  int64 //未绑定
	)
	err := db.Model(&Device{}).
		Select("devices.id,devices.device_sn AS sn,devices.stock_status,devices.binding_status,agents.agent_name,merchants.merchant_name,devices.binding_time").
		Joins("LEFT JOIN agents ON agents.id = devices.agent_id").
		Joins("LEFT JOIN merchants ON merchants.id = devices.merchant_id").
		Where("FIND_IN_SET(?,devices.agent_id)", agentId).
		Limit(pageSize).
		Offset((pageNum - 1) * pageSize).
		Order("devices.created_at DESC").
		Scan(&result).Error
	if err != nil {
		logrus.WithError(err).Errorf("获取设备信息列表失败 err:%v,agentId:%v", err, agentId)
		return nil, errors.New("获取设备信息列表失败")
	}

	//总数
	db.Model(&Device{}).Where("FIND_IN_SET(?,devices.agent_id)", agentId).Count(&count)
	//待出库
	db.Model(&Device{}).Where("FIND_IN_SET(?,devices.agent_id) AND stock_status = 0", agentId).Count(&dispatchCount)
	//已出库
	db.Model(&Device{}).Where("FIND_IN_SET(?,devices.agent_id) AND stock_status = 1", agentId).Count(&dispatchedCount)
	//未绑定
	db.Model(&Device{}).Where("FIND_IN_SET(?,devices.agent_id) AND binding_status = 0", agentId).Count(&unBindingCount)
	//已绑定
	db.Model(&Device{}).Where("FIND_IN_SET(?,devices.agent_id) AND binding_status = 1", agentId).Count(&bindingCount)

	return map[string]interface{}{
		"count":           count,
		"dispatchCount":   dispatchCount,
		"dispatchedCount": dispatchedCount,
		"unBindingCount":  unBindingCount,
		"bindingCount":    bindingCount,
		"list":            result,
	}, err
}

// DeviceInfo 设备信息
func DeviceInfo(id int) (interface{}, error) {
	var result deviceResponse.GetDeviceInfoResponse
	path := setting.GetConfig().App.RuntimeRootPath + "deviceResponse/"
	selectd := fmt.Sprintf("devices.id,CONCAT('%s',device_models.icon) AS icon,devices.iccid,"+
		"device_models.device_type,devices.device_sn,device_models.device_no,devices.payment_code,"+
		"devices.device_tusn,devices.stock_status,devices.delivery_time,devices.binding_status,devices.binding_time,"+
		"agents.agent_name,CONCAT('P',agents.agent_no) AS agent_no,base.agent_name AS base_agent_name,CONCAT('P',base.agent_no) AS base_agent_no,"+
		"merchants.merchant_name,merchants.merchant_no", path)
	err := db.Model(&Device{}).
		Select(selectd).
		Joins("LEFT JOIN device_models ON devices.device_model_id = device_models.id"). //设备型号
		Joins("LEFT JOIN agents ON devices.agent_id = agents.id").                      //所属代理商
		Joins("LEFT JOIN agents AS base ON devices.base_agent_id = base.id").           //父级代理商
		Joins("LEFT JOIN merchants ON devices.merchant_id = merchants.id").             //所属商户
		Where("devices.id = ?", id).First(&result).Error
	if err != nil {
		logrus.WithError(err).Errorf("获取设备信息失败 err:%v,id:%v", err, id)
		return nil, errors.New("获取设备信息失败")
	}

	if result.DeliveryTime == nil {
		result.DeliveryTime = (*time2.LocalTime)(&time.Time{})
	}

	if result.BindingTime == nil {
		result.BindingTime = (*time2.LocalTime)(&time.Time{})
	}

	if len(result.MerchantNo) != 0 {
		result.MerchantNo = "M" + result.MerchantNo
	}

	return result, err
}

// DeviceAllocateInfoList 获取划拨设备列表
func DeviceAllocateInfoList(agentId, deviceModeId, pageNum, pageSize int) (map[string]interface{}, error) {
	var (
		result = make([]*deviceResponse.GetDeviceAllocateInfoListResponse, 0)
		count  int64
	)

	err := db.Model(&Device{}).Select("id,device_sn AS sn,device_tusn AS tusn,payment_code AS codeService").
		Where("agent_id = ? AND activate_status = 0 AND binding_status = 0 AND device_model_id = ?", agentId, deviceModeId).
		Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("created_at DESC").Scan(&result).Error

	if err != nil {
		logrus.WithError(err).Errorf("获取划拨设备列表失败 err:%v,agentId:%v", err, agentId)
		return nil, errors.New("获取划拨设备列表失败")
	}

	db.Model(&Device{}).
		Where("agent_id = ? AND activate_status = 0 AND binding_status = 0 AND device_model_id = ?", agentId, deviceModeId).
		Count(&count)

	return map[string]interface{}{
		"list":  result,
		"count": count,
	}, nil
}

// DeviceRecallInfoList 获取可召回设备列表
func DeviceRecallInfoList(agentId, deviceModeId, pageNum, pageSize int) (map[string]interface{}, error) {
	var (
		result = make([]*deviceResponse.GetDeviceAllocateInfoListResponse, 0)
		count  int64
	)

	err := db.Model(&Device{}).Select("id,device_sn AS sn,device_tusn AS tusn,payment_code AS codeService").
		Where("agent_id = ? AND activate_status = 0 AND binding_status = 0 AND device_model_id = ?", agentId, deviceModeId).
		Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("created_at DESC").Scan(&result).Error

	if err != nil {
		logrus.WithError(err).Errorf("获取划拨设备列表失败 err:%v,agentId:%v", err, agentId)
		return nil, errors.New("获取划拨设备列表失败")
	}

	db.Model(&Device{}).
		Where("agent_id = ? AND activate_status = 0 AND binding_status = 0 AND device_model_id = ?", agentId, deviceModeId).
		Count(&count)

	return map[string]interface{}{
		"list":  result,
		"count": count,
	}, nil
}

// DeviceRecallAgentList 获取可召回代理列表
func DeviceRecallAgentList(agentId, deviceModeId, pageNum, pageSize int) (map[string]interface{}, error) {
	var (
		result = make([]*deviceResponse.GetDeviceRecallInfoListResponse, 0)
		count  int64
	)

	err := db.Model(&AgentRelation{}).Select("agents.agent_name,CONCAT('P',agents.agent_no) AS agent_no,COUNT(DISTINCT devices.id) AS device_count").
		Joins("LEFT JOIN devices ON devices.agent_id = agent_relations.agent_id AND devices.device_model_id = ?", deviceModeId).
		Joins("LEFT JOIN agents ON agent_relations.agent_id = agents.id").
		Where("FIND_IN_SET(?, agent_relations.relation ) AND agent_relations.agent_id <> ?", agentId, agentId).
		Group("agents.agent_id").
		Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("agents.created_at DESC").Scan(&result).Error

	if err != nil {
		logrus.WithError(err).Errorf("获取划拨设备列表失败 err:%v,agentId:%v", err, agentId)
		return nil, errors.New("获取划拨设备列表失败")
	}

	db.Model(&AgentRelation{}).
		Where("FIND_IN_SET(?, agent_relations.relation ) AND agent_relations.agent_id <> ?", agentId, agentId).
		Count(&count)

	return map[string]interface{}{
		"list":  result,
		"count": count,
	}, nil
}

func DeviceInfoListSearch(deviceModeId, pageNum, pageSize int, condition string) (map[string]interface{}, error) {
	var (
		result = make([]*deviceResponse.GetDeviceAllocateInfoListResponse, 0)
		count  int64
	)

	err := db.Model(&Device{}).Select("id,device_sn AS sn,device_tusn AS tusn,payment_code AS codeService").
		Where(fmt.Sprintf("%s AND device_model_id = %d", condition, deviceModeId)).
		Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("created_at DESC").Scan(&result).Error

	if err != nil {
		logrus.WithError(err).Errorf("获取划拨设备列表失败 err:%v,deviceModeId:%v", err, deviceModeId)
		return nil, errors.New("获取划拨设备列表失败")
	}

	db.Model(&Device{}).
		Where(fmt.Sprintf("%s AND device_model_id = %d", condition, deviceModeId)).
		Count(&count)

	return map[string]interface{}{
		"list":  result,
		"count": count,
	}, nil
}

// DeviceMerchantAdd 商户添加设备
func DeviceMerchantAdd(merchantId, deviceSn any) error {
	var dev *Device
	db.Model(&Device{}).Where("device_sn = ?", deviceSn).Scan(dev)
	if dev.ID == 0 || dev.MerchantId != 0 {
		return errors.New("添加设备失败")
	}

	db.Model(&Device{}).Where("device_sn = ?", deviceSn).Updates(map[string]interface{}{
		"merchant_id":   merchantId,
		"stock_status":  1,
		"delivery_time": time.Now(),
	})
	return nil
}
